// 导入threejs
import * as THREE from "three";

export default function particlesAnimate(
  mesh, //你要变成动态粒子的物体
  ...res
) {
  const [
    clock,
    currentMouse,
    mouse,
    raycaster,
    camera,
    scene,
    plane,
    currentPage,
  ] = res;
  const pointsGeometry = mesh.geometry;
  const material = mesh.material;
  // 偏移量
  let offsetRadius = mesh.name === "RandomSpacePoints" ? 0.3 : 0.02;

  // 鼠标的影响幅度
  let mouseOffset = 0.2;
  //鼠标影响距离
  let distanceScale = 0.5

  const points = new THREE.Points(pointsGeometry, material);
  // 将初始位置存储下来，用于后续的动画计算
  let initialPositions = pointsGeometry.attributes.position.array.slice();
  let initialColors = pointsGeometry.attributes.color.array.slice();
  let initialSizes = pointsGeometry.attributes.vSize.array.slice();

  // 渲染循环函数中更新粒子动画
  function animateParticles() {
    const elapsedTime = clock.getElapsedTime(); // 获取自从时钟启动后的总时间
    const positions = pointsGeometry.attributes.position.array; // 获取粒子的位置数据
    const colors = pointsGeometry.attributes.color.array; // 获取粒子颜色数据
    const sizes = pointsGeometry.attributes.vSize.array; // 获取粒子大小数据
    const randomDirections = pointsGeometry.attributes.randomDirection // 随机方向
      ? pointsGeometry.attributes.randomDirection.array
      : undefined;
    const randomSpeeds = pointsGeometry.attributes.randomSpeed // 随机速度
      ? pointsGeometry.attributes.randomSpeed.array
      : undefined;
    const randomPositions = pointsGeometry.attributes.randomPosition
      ? pointsGeometry.attributes.randomPosition.array
      : undefined; // 随机初始位置

    // 真实鼠标位置
    currentMouse.x = THREE.MathUtils.lerp(currentMouse.x, mouse.x, 0.05);
    currentMouse.y = THREE.MathUtils.lerp(currentMouse.y, mouse.y, 0.05);
    // 点稍微旋转一下(旋转模型)
    points.rotation.x =
      Math.sin(elapsedTime * 0.2) * 0.2 - currentMouse.x * 0.2 * mouseOffset;
    points.rotation.z =
      Math.sin(elapsedTime * 0.2) * 0.1 - currentMouse.y * 0.2 * mouseOffset;

    // 更新 Raycaster 的方向和位置
    raycaster.setFromCamera(mouse, camera);

    // 获取与点的交叉信息
    const intersects = raycaster.intersectObject(plane);

    // 粒子数组
    const referPositions = new Float32Array(
      pointsGeometry.attributes.position.array.length
    );
    for (let i = 0; i < positions.length; i += 3) {
      // 获取初始位置
      const initialX = initialPositions[i];
      const initialY = initialPositions[i + 1];
      const initialZ = initialPositions[i + 2];
      // 获取当前粒子的运动方向和速度
      const direction = {
        x: randomDirections[i / 3],
        y: randomDirections[i / 3 + 1],
        z: randomDirections[i / 3 + 2],
      };
      const speed = randomSpeeds[i / 3];

      // 根据时间和速度生成随机摆动动画
      const offsetX =
        Math.sin(elapsedTime * speed + initialX) * direction.x * offsetRadius;
      const offsetY =
        Math.sin(elapsedTime * speed + initialY) * direction.y * offsetRadius;
      const offsetZ =
        Math.sin(elapsedTime * speed + initialZ) * direction.z * offsetRadius;

      // 更新粒子的位置
      referPositions[i] = initialX + offsetX;
      referPositions[i + 1] = initialY + offsetY;
      referPositions[i + 2] = initialZ + offsetZ;
      // 默认粒子大小为 1
      let targetSize = 1;
      let stepLength = 0.1;
      let currentPosition;

      if (randomPositions != undefined) {
        currentPosition = {
          x:
            referPositions[i] +
            randomPositions[i] *
              Math.sin((currentPage.value % 10) * Math.PI * 0.1),
          y:
            referPositions[i + 1] +
            randomPositions[i + 1] *
              Math.sin((currentPage.value % 10) * Math.PI * 0.1),
          z:
            referPositions[i + 2] +
            randomPositions[i + 2] *
              Math.sin((currentPage.value % 10) * Math.PI * 0.1),
        };
      } else {
        currentPosition = {
          x: referPositions[i],
          y: referPositions[i + 1],
          z: referPositions[i + 2],
        };
      }

      // 如果鼠标附近有顶点，将它们放大并四散
      if (intersects.length > 0) {
        const intersectPoint = intersects[0].point; // 获取鼠标的交点位置
        const distance = new THREE.Vector2(
          initialX + points.position.x,
          initialY + points.position.y
        ).distanceTo(new THREE.Vector2(intersectPoint.x, intersectPoint.y));

        if (distance < distanceScale) {
          // 距离阈值，根据需要调整
          targetSize = 2; // 放大粒子

          let targetLength = 0.1;
          // 增加四散效果
          positions[i] = THREE.MathUtils.lerp(
            positions[i],
            currentPosition.x +
              (currentPosition.x - (intersectPoint.x - points.position.x)) *
                targetLength,
            stepLength
          );
          positions[i + 1] = THREE.MathUtils.lerp(
            positions[i + 1],
            currentPosition.y +
              (currentPosition.y - (intersectPoint.y - points.position.y)) *
                targetLength,
            stepLength
          );
          positions[i + 2] = THREE.MathUtils.lerp(
            positions[i + 2],
            currentPosition.z +
              (currentPosition.z - (intersectPoint.z - points.position.z)) *
                targetLength,
            stepLength
          );
          sizes[i / 3] = THREE.MathUtils.lerp(
            sizes[i / 3],
            initialSizes[i / 3] * targetSize,
            0.03
          );
        } else {
          positions[i] = THREE.MathUtils.lerp(
            positions[i],
            currentPosition.x,
            stepLength
          );
          positions[i + 1] = THREE.MathUtils.lerp(
            positions[i + 1],
            currentPosition.y,
            stepLength
          );
          positions[i + 2] = THREE.MathUtils.lerp(
            positions[i + 2],
            currentPosition.z,
            stepLength
          );
          sizes[i / 3] = THREE.MathUtils.lerp(
            sizes[i / 3],
            initialSizes[i / 3],
            0.03
          );
        }
      } else {
        positions[i] = THREE.MathUtils.lerp(
          positions[i],
          currentPosition.x,
          stepLength
        );
        positions[i + 1] = THREE.MathUtils.lerp(
          positions[i + 1],
          currentPosition.y,
          stepLength
        );
        positions[i + 2] = THREE.MathUtils.lerp(
          positions[i + 2],
          currentPosition.z,
          stepLength
        );
        sizes[i / 3] = THREE.MathUtils.lerp(
          sizes[i / 3],
          initialSizes[i / 3],
          0.03
        );
      }

      // 根据时间和速度生成随机颜色
      colors[i] =
        initialColors[i] +
        Math.sin(elapsedTime * speed + initialX + initialColors[i]) * 0.1;
      colors[i + 1] =
        initialColors[i + 1] +
        Math.sin(elapsedTime * speed + initialY + initialColors[i + 1]) * 0.1;
      colors[i + 2] =
        initialColors[i + 2] +
        Math.sin(elapsedTime * speed + initialZ + initialColors[i + 2]) * 0.1;
    }

    // 通知Three.js更新粒子的几何体
    pointsGeometry.attributes.position.needsUpdate = true;
    pointsGeometry.attributes.color.needsUpdate = true;
    pointsGeometry.attributes.vSize.needsUpdate = true; // 标记需要更新
    requestAnimationFrame(animateParticles);
  }
  animateParticles();

  return points;
}
